# coding=utf8
import re
import random
import time
import json
import calendar
import requests
import datetime
from datetime import date


# 匹配多个正则表达式 返回group(1)
def analy_re_search(content, patterns, israise=True, isstrip=True, raisemsg="", isprice=False, default="", subt=None,
                    subres=None):
    if subres is None:
        subres = []
    if type(patterns) is type(''):
        patterns = [patterns]
    if not isinstance(content, bytes):
        content = content.encode()

    for pattern in patterns:
        if not isinstance(pattern, bytes):
            pattern = pattern.encode()

        re_1 = re.search(pattern, content)
        if re_1 and re_1.groups():
            try:
                message = re_1.group(1)
            except:
                continue

            if subt or subres:
                message = _sub(message, t=subt, res=subres)

            if isstrip:
                message = message.strip()
                if isprice:
                    if message == "" or message == "0" or message == "0.0":
                        continue
                return message.decode()
            else:
                return message.decode()
    else:
        if israise:
            raise Exception("**** {1} re data is error :{0}\n".format(patterns, raisemsg))
        else:
            if isinstance(default, bytes):
                default = default.decode()
            return default


# 匹配多个正则表达式 返回groups()
def analy_re_groups(content, patterns, israise=True, raisemsg=None):
    if type(patterns) is type(''):
        patterns = [patterns]
    for pattern in patterns:
        re_1 = re.search(pattern, content)
        if re_1:
            return re_1.groups()
    else:
        if israise:
            if raisemsg:
                raise Exception(raisemsg)
            raise Exception("**** re group is error :{0}\n".format(patterns))
        else:
            return None


# 匹配多个xpath 返回extract()
def analy_xpath(_select, _xpaths, israise=False, isfirst=True, isstrip=True, subt=None, subres=None):
    if subres is None:
        subres = []
    if type(_xpaths) is type(''):
        _xpaths = [_xpaths]

    for path in _xpaths:
        if not isinstance(path, bytes):
            path = path.encode()

        try:
            result = _select.xpath(path)
        except:
            result = []

        if len(result) > 0:
            if isfirst:
                if isstrip:
                    result = result[0].extract().strip()
                else:
                    result = result[0].extract()
                if subt or subres:
                    result = _sub(result, res=subres, t=subt)
            return result

    if israise:
        raise Exception("&&&& select xpaths is not find : {0}".format(_xpaths))
    if isfirst:
        return ""
    return []


# 正则替换文本内容
def _sub(content, res=None, t=None):
    if not isinstance(content, bytes):
        content = content.encode()

    if res is None:
        res = []
    if t:
        if t == "html1":
            res += [('<script.*?>[\s\S]*?</script>', ' '),
                    ('<style.*?>[\s\S]*?</style>', ' '),
                    ('<[\s\S]*?>', ''), ('\s+', ' '),
                    ('&nbsp;', ' '),
                    ]
        elif t == "html2":
            res += [(r'\\r', ''), (r'\\n', ''), (r'\\t', ''),
                    (r'\\/', '/'), (r'\\"', '"'), ('\s+', ' ')
                    ]
        elif t == "html3":
            res += [(r'&amp;', '&'), ('&nbsp;', ' '),
                    ]
        elif t == "url1":
            res += [(r'&amp;', '&'),
                    ]

    if type(res) not in [type([]), type(())]:
        print("res type is nt list : {0}".format(res))
        return

    for rei in res:
        rei0 = rei[0] if isinstance(rei[0], bytes) else rei[0].encode()
        rei1 = rei[1] if isinstance(rei[1], bytes) else rei[1].encode()
        content = re.sub(rei0, rei1, content)

    return content.decode()


# findall匹配多个正则表达式 返回多维数组
def analy_re_findall(content, patterns, israise=True):
    if not isinstance(content, bytes):
        content = content.encode()

    if type(patterns) is type(''):
        patterns = [patterns]
    datas = []
    for index, pattern in enumerate(patterns):
        if not isinstance(pattern, bytes):
            pattern = pattern.encode()

        list1 = re.findall(pattern, content)
        if len(list1) == 0:
            continue
        for li in list1:
            if isinstance(li, str) or isinstance(li, bytes):
                if li.strip() != "":
                    datas.append(li.strip())
            else:
                datas.append(li)

    return datas


def get_timestamp(digit=10, _time=None):
    if digit < 10:
        raise Exception("the get_timestamp digit is not less than 10 !")

    if _time:
        timestamp = str(int(_time))
    else:
        timestamp = str(int(time.time()))

    while len(timestamp) < digit:
        timestamp += str(random.randint(0, 9))
    return str(timestamp)


def random_floatnumber(bnumber, addnumber=1):
    if type(bnumber) not in [int, float]:
        raise Exception("the random_floatnumber bnumber or addnumber is must type int !")
    numbers = []
    nnumber = float(bnumber)
    while nnumber <= bnumber + addnumber:
        numbers.append(round(nnumber, 2))
        nnumber += 0.01
    return random.choice(numbers)


def random_ss_tp(tp, ss=[], span=1):
    tp = str(tp)

    try:
        if isinstance(tp, bytes):
            tp = tp.decode()

        if tp == "short":
            ss = [
                0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
                1.0, 1.1, 1.2, 1.3, 1.4, 1.5,
            ]
        elif tp == "long":
            ss = [
                10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9,
                11.0, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9,
            ]
        elif tp == "scroll":
            ss = [
                0.1, 0.2, 0.3, 0.4, 0.5
            ]
        elif type(eval(tp)) in [int, float]:
            ss = [random_floatnumber(eval(tp), addnumber=span)]
        elif tp == "1":
            ss = [1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9]
        elif tp == "2":
            ss = [2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9]
        elif ss:
            ss = ss
        else:
            ss = [0]
        return eval(random.choice(ss))
    except:
        return 0.5


def random_string(count):
    return "8856"


def random_screen_resolution():
    resolutions = [
        (1920, 1080), (1366, 768), (1440, 900), (1600, 900),
        (1024, 768), (1280, 1024), (1680, 1050), (1280, 800),
        (1366, 768), (800, 600),
    ]
    resolution = random.choice(resolutions)
    return {"width": resolution[0], "height": resolution[1]}


def get_timelastmonths(format="%Y%m", count=1, iscurrent=True, earliest_time=0):
    times = []
    now_time = time.mktime(time.strptime(time.strftime("%Y-%m"), "%Y-%m"))

    # 提前遍历出大于月份倍数+2的数据出来
    for i in range(int(count / 12) + 2):
        year = int(time.strftime("%Y")) - i
        for j in range(0, 12):
            month = 12 - j
            timeArray = time.strptime("{0}-{1}".format(year, month), "%Y-%m")
            times.append(int(time.mktime(timeArray)))

    results = []
    for timei in times:
        if len(results) >= count:
            break
        if iscurrent:
            if timei > now_time:
                continue
        else:
            if timei >= now_time:
                continue

        if earliest_time and timei < earliest_time:
            # 小于开户时间的月份排除掉
            continue

        results.append(time.strftime(format, time.localtime(timei)))

    return results


def get_timelastmonth(format="%Y%m", count=0):
    times = []
    now_time = time.mktime(time.strptime(time.strftime("%Y-%m"), "%Y-%m"))

    # 提前遍历出大于月份倍数+2的数据出来
    for i in range(2):
        year = int(time.strftime("%Y")) - i
        for j in range(0, 12):
            month = 12 - j
            timeArray = time.strptime("{0}-{1}".format(year, month), "%Y-%m")
            times.append(int(time.mktime(timeArray)))

    n = 0
    for timei in times:
        if timei > now_time:
            continue

        if n >= count:
            return time.strftime(format, time.localtime(timei))

        n += 1

    raise Exception("get_timelastmonth error")


def get_timelastday(year, month, iscurrent=False):
    year = int(year)
    month = int(month)

    if int(month) in (1, 3, 5, 7, 8, 10, 12):
        day = 31
    elif int(month) == 2:
        if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
            day = 29
        else:
            day = 28
    else:
        day = 30

    format = "%Y-%m"
    now_time = time.strptime(time.strftime(format), format)
    appoint_time = time.strptime("{0}-{1}".format(year, month), format)

    if iscurrent and now_time == appoint_time:
        return str(time.strftime("%d"))
    else:
        return str(day)


def generate_querydate(date, days=1, expression="%Y-%m-%d"):
    if days > 0:
        return {
            "$gte": datetime.datetime.strptime(date, expression),
            "$lte": datetime.datetime.strptime(date, expression) + datetime.timedelta(days=days)
        }
    elif days < 0:
        return {
            "$gte": datetime.datetime.strptime(date, expression) - datetime.timedelta(days=days),
            "$lte": datetime.datetime.strptime(date, expression)
        }
    else:
        return {
            "$gte": datetime.datetime.strptime(date + " 00:00:00", expression + " %h:%m:%s"),
            "$lte": datetime.datetime.strptime(date + " 23:59:59", expression + " %h:%m:%s")
        }


def sequence_week(sequence=None, week=None, today=None):
    """

    :param sequence: last, next
    :param week: MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    :return:
    """

    if not today:
        today = datetime.date.today()

    if not isinstance(today, date):
        raise Exception("指定日志必须是date类型")

    if sequence is None or sequence == "current":
        return today

    if week is None or not hasattr(calendar, week):
        raise Exception("星期内容不合规范")

    if sequence != "last" and sequence != "next":
        raise Exception("序列内容不合规范")

    if sequence == "last":
        while today.weekday() != getattr(calendar, week):
            today -= datetime.timedelta(days=1)
    elif sequence == "next":
        while today.weekday() != getattr(calendar, week):
            today += datetime.timedelta(days=1)

    return today


def dingding_robot(url, content, **kwargs):
    """
    给钉钉机器人发消息
    :param url: https://oapi.dingtalk.com/robot/send?access_token=c901b5272b376f3317d272955bb3a99807e1aee1ad3489ab9e2089926d10d7c0
    :param content:
    :param kwargs: {"atMobiles": atMobiles, "isAtAll": isAtAll}
    :return:
    """

    headers = {"Content-Type": "application/json"}
    data = json.dumps({
        "msgtype": "text",
        "text": {"content": content},
        "at": kwargs
    })
    response = requests.post(url, data=data, headers=headers, verify=False)
    return response.content
